package middleware

import (
	"fmt"
	"net/http"
	"net/http/httputil"
	"runtime"
	"strconv"

	"github.com/gin-gonic/gin"

	"gsms/pkg/ecode"
	"gsms/pkg/wechat"
)

const _message = `
### <font color="warning">%s有bug了, 请及时处理!!!</font>
#### <font color="info">request:</font>
    %s
#### <font color="info">response:</font>
    %s
#### <font color="info">trace_log:</font>
    %s
`

// Errors 统一错误处理
func Errors() gin.HandlerFunc {
	return func(c *gin.Context) {
		defer func() {
			if r := recover(); r != nil {
				buf := make([]byte, 64<<10)
				buf = buf[:runtime.Stack(buf, false)]
				errInfo := fmt.Sprintf("gsms: panic recovered: %s\n%s", r, buf)
				c.JSON(http.StatusInternalServerError, ecode.ServerError)
				notifyWeixin(c, errInfo)
				return
			}
		}()

		c.Next() // execute all the handlers

		// at this point, all the handlers finished. Let's read the errors!
		// in this example we only will use the **last error typed as public**
		// but you could iterate over all them since c.Errors is a slice!
		errorToPrint := c.Errors.ByType(gin.ErrorTypePrivate).Last()
		if errorToPrint != nil {
			var err *ecode.Error
			if e, ok := errorToPrint.Err.(*ecode.Error); ok {
				err = e
				c.JSON(err.StatusCode, err)
				return
			}
			errInfo := fmt.Sprintf("%+v", errorToPrint.Err)
			c.JSON(http.StatusInternalServerError, ecode.ServerError)
			notifyWeixin(c, errInfo)
			return
		}
	}
}

func notifyWeixin(c *gin.Context, errInfo string) {
	data, _ := httputil.DumpRequest(c.Request, false)
	message := fmt.Sprintf(_message, "短信服务", string(data), requestID(c.Request), errInfo)
	go func() {
		_ = wechat.SendMarkDown(strconv.Quote(message))
	}()
	return
}
